import json

from django.contrib.messages.api import success
from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated
from order.models import Order, OrderDetail
from payments import models, ser
from utils.snowflake import SnowflakeSingleton
from .tasks import send_order_success_email, update_order_status
from .wxpay import WxPayClient


class Payment(APIView):
    permission_classes = [IsAuthenticated]

    def post(self, request):
        # 1.获取参数
        user = request.user
        order_number = request.data.get("order_number")
        # 2.判断参数order_number
        if not order_number:
            return Response({"message": "订单号不能为空"}, status=400)
        order = Order.objects.filter(order_number=order_number, user=user.id).first()
        # 3.判断这个订单是不是这个用户的
        if not order:
            return Response({"message": "订单不存在"}, status=400)
        # 4.创建支付记录
        flake = SnowflakeSingleton.get_instance(worker_id=2)
        payment_info = {
            "order": order.id,
            "order_number": order.order_number,
            "pay_order_number": flake.get_id(),
            "pay_amount": order.total,
        }
        res = ser.PaymentSerializer(data=payment_info)
        if not res.is_valid():
            return Response({'msg': res.errors, 'status': 400})
        res.save()
        # 5.调用支付的函数
        wxpay = WxPayClient()
        money = int(float(order.total) * 100)
        code_url = wxpay.create_order(str(order_number), money, '课程支付')
        print(code_url)
        if not code_url:
            return Response({"message": "发取微信支付失败"}, status=400)
        # 将pay_remark修改成 正在发起微信支付
        payment = models.Payment.objects.filter(order_number=order_number).first()
        payment.pay_remark = '正在发起微信支付'
        payment.save()
        # 6.返回支付连接结果
        result = {
            "code_url": code_url,
            'order_number': order_number,
            'pay_amount': order.total,
            'pay_order_number': payment.pay_order_number,
        }
        # 开始计时 1分钟 如果1分钟没有支付 就超时取消
        update_order_status.apply_async(args=[order_number], countdown=60)
        return Response({'msg': '发起支付成功', 'status': 200, 'result': result})


class Notify(APIView):
    def post(self, request):
        # 获取参数
        body_byte = request.body or b''  # 如果为空 设置一个空的二进制防止转码报错
        payload = json.loads(body_byte.decode('utf-8')) if body_byte else {}
        # 2 获取到事件的类型以及 resource
        event_type = payload.get('event_type')  # 事件类型
        resource = payload.get('resource')   # 资源
        if not resource:
            return Response({'msg': '支付失败', 'code': 400})
        # 3 验证签名  成功后会返回一个标志True
        wxpay = WxPayClient()
        if not wxpay.verify_callback_signature(request.headers, body_byte.decode('utf8')):
            return Response({'msg': '验证签名失败', 'code': 400})
        # 4 对返回的resource 进行解密处理
        try:
            resource_dict = wxpay.decrypt_notification(resource)
        except:
            return Response({'msg': '解密失败', 'code': 400})
        # 5 获取返回的数据
        out_trade_no = resource_dict.get('out_trade_no')  # 商户订单号
        transaction_id = resource_dict.get('transaction_id')  # 微信支付订单号
        trade_status = resource_dict.get('trade_state')  # 交易状态
        success_time_str = resource_dict.get('success_time')  # 支付成功时间
        amount_info = resource_dict.get('amount') or {}  # 订单金额
        payer_info = resource_dict.get('payer') or {}  # 付款人
        # 6 根据订单查询自己订单信息 做一些业务数据的改变 修改订单表  修改我们支付记录表
        order_info = Order.objects.filter(order_number=out_trade_no).first()
        if not order_info:
            return Response({'msg': '订单不存在', 'code': 400})
        if order_info.status == 1:
            return Response({'msg': '订单已支付', 'code': 400})
        # 7 修改订单状态
        order_info.status = 1
        order_info.pay_time = success_time_str
        order_info.save()
        # 8 修改支付记录表
        order_payment = models.Payment.objects.filter(order_number=out_trade_no).first()
        order_payment.trade_no = transaction_id
        order_payment.pay_status = 1
        order_payment.pay_time = success_time_str
        order_payment.pay_remark = '微信支付已完成'
        order_payment.save()
        return Response({'msg': '支付成功', 'code': 200})


class Select(APIView):
    permission_classes = [IsAuthenticated]

    # 1 查询参数
    def get(self, request):
        order_number = request.query_params.get('order_number')
        if not order_number:
            return Response({'msg': '订单号不能为空', 'code': 400})
        # 2 查询订单(是否为当前用户的订单)
        order_info = Order.objects.filter(order_number=order_number, user=request.user.id).first()
        if not order_info:
            return Response({'msg': '订单不存在', 'code': 400})
        # 3查看订单的状态
        if order_info.status == 1:
            # 发送邮件
            course_name = get_course_name(order_number)
            send_order_success_email(request.user.username, '3181444897@qq.com', order_number, course_name)
            print('发送邮件成功')
            return Response({'msg': '订单已支付', 'code': 400})
        # 4 订单的状态没有及时跟新  就去订单的支付记录表查询
        payment_info = models.Payment.objects.filter(order_number=order_number).first()
        if payment_info and payment_info.pay_status == 1:
            # 说明 用户已经支付了 但是订单表没有更新 做什么（修改订单表的状态 返回用户支付成功的信息）
            order_info.status = 1
            order_info.pay_no = payment_info.trade_no
            order_info.pay_time = payment_info.pay_time
            order_info.save()
            # 发送邮件
            course_name = get_course_name(order_number)
            send_order_success_email(request.user.username, '3181444897@qq.com', order_number, course_name)
            return Response({'msg': '支付成功', 'code': 200})
        # 5 还没有查到 就去微信中查询
        wxpay = WxPayClient()
        result = wxpay.query_order(order_number)
        if result.get('trade_state') == 'SUCCESS':
            # 支付成功
            # 修改订单表的状态
            order_info.status = 1
            order_info.pay_no = result.get('transaction_id')
            order_info.pay_time = result.get('success_time')
            order_info.save()
            # 修改支付记录表的状态
            order_info.pay_status = 1
            order_info.trade_no = result.get('transaction_id')
            order_info.pay_time = result.get('success_time')
            order_info.save()
            # 发送邮件
            course_name = get_course_name(order_number)
            send_order_success_email(request.user.username, '3181444897@qq.com', order_number, course_name)
            return Response({'msg': '支付成功', 'code': 200})
        else:
            return Response({'msg': '支付失败', 'code': 400})


# 写一个函数 根据订单号查询到当前课程名字
def get_course_name(order_number):
    order_info = OrderDetail.objects.filter(order_number=order_number)
    # 设置一个空字符串
    courses = ''
    # 遍历结果集 拼接课程名称
    for item in order_info:
        courses += item.course.name + ','
    # 去掉最后一个
    return courses[:-1]
